#include <STDIO.H>
#include <WINDOWS.H>
#include "Server\prime.h"
#include "directio.h"

/* If we found a prime then return PRIME, otherwise return NOT_PRIME */

#define PRIME           1
#define NOT_PRIME       0

/* Maximum Number of Clients to respond to */

#define MAX_CALLS      15

/* Coordinates for displaying numbers to be tested */

#define TESTING_X1      3
#define TESTING_Y1      3
#define TESTING_X2     23
#define TESTING_Y2     18

/* Coordinates for displaying prime numbers */

#define PRIME_X1       30
#define PRIME_Y1        3
#define PRIME_X2       50
#define PRIME_Y2       18

#define ERROR_EXIT      2
#define SUCCESS_EXIT    0
#define STRING_LENGTH 256

/* Delay time in microseconds */

#define WAIT          350
#define WAIT_DISPLAY 2000

/* Colors used in this application */

#define WHITE_ON_BLUE FOREGROUND_WHITE|FOREGROUND_INTENSITY|BACKGROUND_BLUE
#define WHITE_ON_CYAN FOREGROUND_WHITE|FOREGROUND_INTENSITY|BACKGROUND_CYAN
#define RED_ON_BLUE   FOREGROUND_RED|FOREGROUND_INTENSITY|BACKGROUND_BLUE
#define RED_ON_CYAN   FOREGROUND_RED|FOREGROUND_INTENSITY|BACKGROUND_CYAN
#define CYAN_ON_CYAN  FOREGROUND_CYAN|BACKGROUND_CYAN

/* Number of characters in computer name to display on the screen */

#define COMP_NAME_LENGTH 7

extern char IsPrime(unsigned long TestNumber);
extern void Usage(void);
extern void InitializeApplication(void);
extern unsigned long NoPrimes[MAX_CALLS];
extern unsigned long handles;
extern void thread_server(void);
extern char GlobalComputerNameBuffer[MAX_CALLS][MAX_COMPUTERNAME_LENGTH];

DWORD  lpIDThread;
HANDLE hthread_server;
CRITICAL_SECTION GlobalCriticalSection;

RPC_BINDING_VECTOR * pBindingVector;

void main(int argc, char **argv)
   {
   RPC_STATUS status;

   unsigned char *pszProtocolSequence = "ncacn_np";
   unsigned char *pszSecurity         = NULL;
   unsigned char *pszEndpoint         = "\\pipe\\prime";
   unsigned int cMinCalls             = 1;
   unsigned int cMaxCalls             = MAX_CALLS;
   unsigned int fDontWait             = FALSE;

   int i;

   /* allow the user to override settings with command line switches */

   for(i = 1; i < argc; i++)
      {
      if((*argv[i] == '-') || (*argv[i] == '/'))
         {
         switch(tolower(*(argv[i]+1)))
            {
            case 'p': /* protocol sequence */
               pszProtocolSequence = argv[++i];
               break;

            case 'e':
               pszEndpoint = argv[++i];
               break;

            case 'm':
               cMaxCalls = (unsigned int) atoi(argv[++i]);
               break;

            case 'n':
               cMinCalls = (unsigned int) atoi(argv[++i]);
               break;

            case 'f':
               fDontWait = (unsigned int) atoi(argv[++i]);
               break;

            case 's':
               pszSecurity = argv[++i];
               break;

            case 'h':
            case '?':
            default:
               Usage();
            }
         }
      else
         Usage();
      }

   status = RpcServerUseProtseqEp(
      pszProtocolSequence,
      cMaxCalls,     /* max concurrent calls */
      pszEndpoint,
      pszSecurity);  /* Security descriptor  */

   if(status)
      {
      printf("RpcServerUseProtseqEp  %d\n", status);
      exit(status);
      }

   status = RpcServerRegisterIf(
      prime_v1_0_s_ifspec,   /* interface to register          */
      NULL,                  /* MgrTypeUuid                    */
      NULL);                 /* MgrEpv; null means use default */

   if(status)
      {
      printf("RpcServerRegisterIf  %d\n", status);
      exit(status);
      }

   InitializeCriticalSection(&GlobalCriticalSection);

   InitializeApplication();

   mxyputs(23, 21, "Listening for prime number requests.", RED_ON_CYAN);

   status = RpcServerListen(cMinCalls, cMaxCalls, fDontWait);

   if(status)
      exit(status);

   if(fDontWait)
      {
      status = RpcMgmtWaitServerListen(); /* wait operation */

      if(status)
         exit(status);
      }
   }

void Usage(void)
   {
   printf("\nDistributed client/server prime number example.\n\n");
   printf("Usage: PRIME\n");
   printf(" -p protocol_sequence\n");
   printf(" -e endpoint\n");
   printf(" -m maxcalls\n");
   printf(" -n mincalls\n");
   printf(" -f flag_wait_op\n");
   printf(" -s security_descriptor\n");
   exit(EXIT_SUCCESS);
   }

/* MIDL allocate and free */
void __RPC_FAR *__RPC_API midl_user_allocate(size_t len)
   {
   return(malloc(len));
   }

void __RPC_API midl_user_free(void __RPC_FAR *ptr)
   {
   free(ptr);
   }

void InitializeApplication(void)
   {
   set_vid_mem();

   clearscreen(BACKGROUND_CYAN);

   box(0, 0, 79, 24, DOUBLE);
   mxyputs(37, 0, " PRIMES ", WHITE_ON_CYAN);

   mxyputs(TESTING_X1, 2, "Testing...", WHITE_ON_CYAN);

   box(TESTING_X1, TESTING_Y1, TESTING_X2, TESTING_Y2,SINGLE);

   mxyputs(PRIME_X1, 2, "Prime!", WHITE_ON_CYAN);
   box(PRIME_X1, PRIME_Y1, PRIME_X2, PRIME_Y2, SINGLE);

   mxyputs(32, 23, "Press Esc to exit", WHITE_ON_CYAN);

   hthread_server = CreateThread(NULL, 0,
      (LPTHREAD_START_ROUTINE)thread_server, NULL,
      CREATE_SUSPENDED, &lpIDThread);

   SetThreadPriority(hthread_server, THREAD_PRIORITY_LOWEST);
   ResumeThread(hthread_server);
   }

void thread_server()
   {
   while(1)
      {
      char Buffer[STRING_LENGTH], Buffert[STRING_LENGTH];
      unsigned char i;

      if(VK_ESCAPE == get_character_no_wait())
         {
         EnterCriticalSection(&GlobalCriticalSection);
         Sleep(WAIT);
         clearscreen(0);
         exit(EXIT_SUCCESS);
         LeaveCriticalSection(&GlobalCriticalSection);
         DeleteCriticalSection(&GlobalCriticalSection);
         }

      if(handles)
         {
         mxyputs(58, 2, "Number of Primes", WHITE_ON_CYAN);
         EnterCriticalSection(&GlobalCriticalSection);
         for(i = 0; i < handles; i++)
            {
            strncpy(Buffert, strupr(GlobalComputerNameBuffer[i]),
               COMP_NAME_LENGTH);
            Buffert[COMP_NAME_LENGTH] = 0;
            sprintf(Buffer, " %7s:%5d ", Buffert, NoPrimes[i]);
            mxyputs(59, (unsigned char)(4+i), Buffer, WHITE_ON_CYAN);
            }

         box(58, 3, 74, (unsigned char)(4+handles), SINGLE);
         mxyputc(58, (unsigned char)(5+i), (char)32, 17, CYAN_ON_CYAN);
         LeaveCriticalSection(&GlobalCriticalSection);
         }
      else
         for(i = 0; i < 13; i++)
            mxyputc(58, (unsigned char)(2+i), (char)32, 17, CYAN_ON_CYAN);

      if(!handles)
         {
         mxyputs(23, 21, "Listening for prime number requests.",
            RED_ON_CYAN);
         Sleep(WAIT_DISPLAY);
         }

      mxyputc(23, 21, (char)32, 36, CYAN_ON_CYAN);
      }
   }

